package cn.edu.xmu.oomall.share.dao;

import cn.edu.xmu.oomall.core.util.Common;
import cn.edu.xmu.oomall.core.util.ReturnNo;
import cn.edu.xmu.oomall.core.util.ReturnObject;
import cn.edu.xmu.oomall.share.mapper.SharePoMapper;
import cn.edu.xmu.oomall.share.mapper.SuccessfulSharePoMapper;
import cn.edu.xmu.oomall.share.model.bo.Share;
import cn.edu.xmu.oomall.share.model.po.SharePo;
import cn.edu.xmu.oomall.share.model.po.SharePoExample;
import cn.edu.xmu.oomall.share.model.po.SuccessfulSharePo;
import cn.edu.xmu.oomall.share.model.po.SuccessfulSharePoExample;
import cn.edu.xmu.oomall.share.model.vo.LiquidationShareRetVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static cn.edu.xmu.privilegegateway.annotation.util.Common.cloneVo;
import static cn.edu.xmu.privilegegateway.annotation.util.Common.setPoCreatedFields;
import static cn.edu.xmu.privilegegateway.annotation.util.Common.setPoModifiedFields;
import static cn.edu.xmu.oomall.core.util.Common.*;

@Repository
public class ShareDao {
    private Logger logger = LoggerFactory.getLogger(ShareDao.class);
    @Autowired
    private SharePoMapper sharePoMapper;

    @Autowired
    private SuccessfulSharePoMapper successfulSharePoMapper;

    private ReturnObject getSharesUsePage(SharePoExample sharePoExample, Integer page, Integer pageSize) {
        try {
            PageHelper.startPage(page, pageSize);

            List<SharePo> sharePoList = sharePoMapper.selectByExample(sharePoExample);
            PageInfo pageInfo = new PageInfo(sharePoList);

            return new ReturnObject(pageInfo);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

//    //Todo 还未确定是不是用gmtCreate时间来判断
//    public ReturnObject getShares(Long productId, LocalDateTime beginDate, LocalDateTime endDate, Integer page, Integer pageSize) {
//        SharePoExample sharePoExample = new SharePoExample();
//        SharePoExample.Criteria criteria = sharePoExample.createCriteria();
//        Optional.ofNullable(productId).ifPresent(x -> criteria.andProductIdEqualTo(x));
//        Optional.ofNullable(beginDate).ifPresent(x -> criteria.andGmtCreateGreaterThanOrEqualTo(x));
//        Optional.ofNullable(endDate).ifPresent(x -> criteria.andGmtCreateLessThanOrEqualTo(x));
//
//        return getSharesUsePage(sharePoExample, page, pageSize);
//    }

    public ReturnObject getShareById(Long shareId) {
        try {
            SharePo sharePo = sharePoMapper.selectByPrimaryKey(shareId);
            if (sharePo == null) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST);
            }

            ReturnObject returnObject = new ReturnObject(cloneVo(sharePo, Share.class));
            return returnObject;
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject insertShare(Long userId, String userName, Long shareActId, Long productId, Long onsaleId) {
        try {
            SharePo sharePo = new SharePo();
            sharePo.setSharerId(userId);
            sharePo.setShareActId(shareActId);
            sharePo.setProductId(productId);
            sharePo.setOnsaleId(onsaleId);
            sharePo.setQuantity(0L);
            setPoCreatedFields(sharePo, userId, userName);

            sharePoMapper.insertSelective(sharePo);
            Share share = cloneVo(sharePo, Share.class);
            return new ReturnObject(share);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject insertSuccessfulShare(Long shareId, Long sharerId, Long productId, Long onsaleId, Long userId) {
        try {
            SuccessfulSharePo successfulSharePo = new SuccessfulSharePo();
            successfulSharePo.setShareId(shareId);
            successfulSharePo.setSharerId(sharerId);
            successfulSharePo.setProductId(productId);
            successfulSharePo.setOnsaleId(onsaleId);
            successfulSharePo.setCustomerId(userId);
            successfulSharePo.setState((byte) 0);

            successfulSharePoMapper.insertSelective(successfulSharePo);
            return new ReturnObject<>(ReturnNo.OK);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject getShares(Long productId, List<Long> shareActIdList, Integer page, Integer pageSize) {
        SharePoExample sharePoExample = new SharePoExample();
        SharePoExample.Criteria criteria = sharePoExample.createCriteria();
        Optional.ofNullable(productId).ifPresent(x -> criteria.andProductIdEqualTo(x));
        Optional.ofNullable(shareActIdList).ifPresent(x -> criteria.andShareActIdIn(shareActIdList));

        return getSharesUsePage(sharePoExample, page, pageSize);
    }

    public ReturnObject getShares(Long userId, Long productId, LocalDateTime beginDate, LocalDateTime endDate, Integer page, Integer pageSize) {
        SharePoExample sharePoExample = new SharePoExample();
        SharePoExample.Criteria criteria = sharePoExample.createCriteria();
        criteria.andSharerIdEqualTo(userId);
        Optional.ofNullable(productId).ifPresent(x -> criteria.andProductIdEqualTo(x));
        Optional.ofNullable(beginDate).ifPresent(x -> criteria.andGmtCreateGreaterThanOrEqualTo(x));
        Optional.ofNullable(endDate).ifPresent(x -> criteria.andGmtCreateLessThanOrEqualTo(x));

        return getSharesUsePage(sharePoExample, page, pageSize);
    }

    private ReturnObject getSuccessfulSharesUsePage(SuccessfulSharePoExample successfulSharePoExample, Integer page, Integer pageSize) {
        try {
            PageHelper.startPage(page, pageSize);

            List<SuccessfulSharePo> successfulSharePoList = successfulSharePoMapper.selectByExample(successfulSharePoExample);
            PageInfo pageInfo = new PageInfo(successfulSharePoList);

            return new ReturnObject(pageInfo);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject getSuccessfulShares(Long userId, Long productId, LocalDateTime beginDate, LocalDateTime endDate, Integer page, Integer pageSize) {
        try {
            SuccessfulSharePoExample successfulSharePoExample = new SuccessfulSharePoExample();
            SuccessfulSharePoExample.Criteria criteria = successfulSharePoExample.createCriteria();
            criteria.andSharerIdEqualTo(userId);
            Optional.ofNullable(productId).ifPresent(x -> criteria.andProductIdEqualTo(x));
            Optional.ofNullable(beginDate).ifPresent(x -> criteria.andGmtCreateGreaterThanOrEqualTo(x));
            Optional.ofNullable(endDate).ifPresent(x -> criteria.andGmtCreateLessThanOrEqualTo(x));

            return getSuccessfulSharesUsePage(successfulSharePoExample, page, pageSize);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public ReturnObject getSuccessfulShares(List<Long> shareActIdList, Long productId, LocalDateTime beginDate, LocalDateTime endDate, Integer page, Integer pageSize) {
        try {
            SharePoExample sharePoExample = new SharePoExample();
            SharePoExample.Criteria sharePoExampleCriteria = sharePoExample.createCriteria();
            if (!shareActIdList.isEmpty()){
                sharePoExampleCriteria.andShareActIdIn(shareActIdList);
            }
            Optional.ofNullable(productId).ifPresent(x -> sharePoExampleCriteria.andProductIdEqualTo(x));
            List<SharePo> sharePoList = sharePoMapper.selectByExample(sharePoExample);
            List<Long> shareIdList = sharePoList.stream().map(SharePo::getId).collect(Collectors.toList());

            SuccessfulSharePoExample successfulSharePoExample = new SuccessfulSharePoExample();
            SuccessfulSharePoExample.Criteria criteria = successfulSharePoExample.createCriteria();
            if (!shareIdList.isEmpty()) {
                criteria.andShareIdIn(shareIdList);
            }
            Optional.ofNullable(beginDate).ifPresent(x -> criteria.andGmtCreateGreaterThanOrEqualTo(x));
            Optional.ofNullable(endDate).ifPresent(x -> criteria.andGmtCreateLessThanOrEqualTo(x));

            return getSuccessfulSharesUsePage(successfulSharePoExample, page, pageSize);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
    }

    public boolean updateBeSharedState(Long id, Byte state) {
        try{
            SuccessfulSharePo successfulSharePo = new SuccessfulSharePo();
            successfulSharePo.setId(id);
            successfulSharePo.setState(state);
            successfulSharePoMapper.updateByPrimaryKeySelective(successfulSharePo);
            return true;
        }
        catch (Exception e)
        {
            logger.error(e.getMessage());
            return false;
        }
    }

    public ReturnObject getBesharedList(Long productId, Long onsaleId, Long customerId) {
        try {
            SuccessfulSharePoExample successfulSharePoExample = new SuccessfulSharePoExample();
            SuccessfulSharePoExample.Criteria successfulSharePoExampleCriteria = successfulSharePoExample.createCriteria();
            if(productId!=null){
                successfulSharePoExampleCriteria.andProductIdEqualTo(productId);
            }
            if(onsaleId!=null){
                successfulSharePoExampleCriteria.andOnsaleIdEqualTo(onsaleId);
            }
            if(customerId!=null){
                successfulSharePoExampleCriteria.andCustomerIdEqualTo(customerId);
            }
            return Common.getListRetVo(new ReturnObject(successfulSharePoMapper.selectByExample(successfulSharePoExample)), LiquidationShareRetVo.class);
        }catch (Exception e)
        {
            logger.error(e.getMessage());
            return null;
        }

    }

    public void addSharesQuantity(Long id, Long quantity) {
        try {
            SharePo sharePo=sharePoMapper.selectByPrimaryKey(id);
            sharePo.setQuantity(sharePo.getQuantity()+quantity);
            sharePoMapper.updateByPrimaryKeySelective(sharePo);
        }
        catch (Exception e)
        {
            logger.error(e.getMessage());
        }
    }

    public ReturnObject getSharesQuantity(Long id) {
        try {
            SharePo sharePo=sharePoMapper.selectByPrimaryKey(id);
            return new ReturnObject(sharePo.getQuantity());
        }
        catch (Exception e)
        {
            logger.error(e.getMessage());
            return null;
        }
    }

    public ReturnObject getSharesByUserAndProduct(Long userId, Long productId) {
        try {
            SharePoExample sharePoExample = new SharePoExample();
            SharePoExample.Criteria criteria = sharePoExample.createCriteria();
            criteria.andSharerIdEqualTo(userId);
            criteria.andProductIdEqualTo(productId);

            List<SharePo> sharePoList = sharePoMapper.selectByExample(sharePoExample);
            if (sharePoList.isEmpty()) {
                return new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST);
            }
            return new ReturnObject(cloneVo(sharePoList.get(0), Share.class));
        }
        catch (Exception e)
        {
            logger.error(e.getMessage());
            return null;
        }
    }
}
